import React, { useState } from 'react';
import AsyncValidator from './async-validate'
class FormStore {

    store = {};
    fieldEntities = [];
    initialValues = {};
    callbacks = {};
    constructor(forceRootUpdate){
        this.forceRootUpdate = forceRootUpdate;
    }

    registerField = (entity) => {
        this.fieldEntities.push(entity);
    };
    setCallbacks = (callbacks) => {
        this.callbacks = callbacks;
    }

    setInitialValues = (initialValues) => {
        this.store = {...initialValues};
    }

    getFieldValue = (name) => {
        return this.store[name];
    }

    getFieldsValue = () => {
        return this.store;
    }

    setFieldsValue = (store) => {
        this.store= { ...this.store,...store};
        this.fieldEntities.forEach(({onStoreChange})=>{
            onStoreChange();
        })
    }

    submit = () => {
        this.validateFields()
        .then(values => {
            const { onFinish } = this.callbacks;
            if (onFinish) {
                onFinish(values);
            }
        })
        .catch(errorInfo => {
            const { onFinishFailed } = this.callbacks;
            if (onFinishFailed) {
                onFinishFailed(errorInfo);
            }
        });
    };
    validateFields = () => {
        let values = this.getFieldsValue();
        let descriptor = this.fieldEntities.reduce((descriptor,entity)=>{
        let rules = entity.props.rules;
        if(rules && rules.length){
            let config = rules.reduce((config,rule)=>{
                config = {...config,...rule};
                return config;
            },{});
            descriptor[entity.props.name]=config;
        }
        return descriptor;
        },{});
        return new AsyncValidator(descriptor).validate(values);
    }

    getForm = () => {
        return {
            setCallbacks: this.setCallbacks,
            registerField: this.registerField,
            setInitialValues: this.setInitialValues,
            getFieldValue: this.getFieldValue,
            getFieldsValue: this.getFieldsValue,
            setFieldsValue: this.setFieldsValue,
            submit: this.submit
        }
    }
}
function useForm(form) {
    const formRef = React.createRef();
    const [,forceUpdate] = useState();
    if(!formRef.current){
        if(form){
            formRef.current = form;
        }else{
            const forceReRender = () => {
                forceUpdate({});
            }
            const formStore = new FormStore(forceReRender);
            formRef.current = formStore.getForm();
        }
    }
    return [formRef.current];
}

export default useForm;
